package org.lee.merge.impl;

import org.lee.export.utils.FileUtils;
import org.lee.merge.IImageMergeStrategy;
import org.lee.merge.MergeException;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * draw for 1 banner and six item for three rows
 *
 * @author jackielee
 * @version 1.0
 * @description DefaultImageMergeStrategy
 * [  ]
 * [][]
 * [][]
 * [][]
 * @date 2021/5/7
 **/
public class DefaultImageMergeStrategy implements IImageMergeStrategy {
    private int width;
    private int height;
    private int bannerIndex;
    private int bannerHeight;
    private int itemHeight;
    private int itemWidth;
    private int margin;
    private int padding;
    private int itemCount;

    public DefaultImageMergeStrategy() {
        this.width = 1000;
        this.bannerIndex = 0;
        this.bannerHeight = 300;
        this.itemHeight = 100;
        this.margin = 20;
        this.padding = 10;
        this.itemCount = 6;
        this.itemWidth = (this.width - this.margin * 2 - this.padding) / 2;
        this.height = this.bannerHeight + this.margin * 2 + this.itemCount * this.itemHeight + (this.itemCount / 2 + 1) * this.padding;
    }

    @Override
    public BufferedImage draw(List<File> files) throws MergeException {
        if (this.bannerIndex >= files.size()) {
            throw new MergeException("banner index not exists in the files");
        }
        if (this.itemCount >= files.size()) {
            throw new MergeException("files not enough for item count");
        }
        BufferedImage img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = img.createGraphics();
        g.setPaint(Color.white);
        g.fill(new Rectangle2D.Float(0, 0, this.width, this.height));
        try {
            int x = this.margin;
            int y = this.margin;
            int bannerWidth = this.width - 2 * this.margin;
            BufferedImage imgBanner = readImage(files.get(this.bannerIndex), bannerWidth, this.bannerHeight);
            int bW = imgBanner.getWidth();
            x = bannerWidth > bW ? (bannerWidth - bW) / 2 + this.margin : x;
            g.drawImage(imgBanner, null, x, y);
            x = this.margin; // restore the x position
            y += this.padding + this.bannerHeight;
            for (int i = 1; i <= this.itemCount; ++i) {
                if (i % 2 == 1 && i > 2) {
                    y += this.padding + (i > 2 ? this.itemHeight : 0);
                    x = this.margin;
                }
                if (i % 2 == 0) {
                    x = this.margin + this.itemWidth + this.padding;
                }
                BufferedImage imgItem = readImage(files.get(i), this.itemWidth, this.itemHeight);
                g.drawImage(imgItem, null, x, y);
            }
            g.dispose();
            return img;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void draw(String path) throws IOException {
        File file = new File(path);
        readImage(file, 300, 200);
        readImage(file, 960, 300);
    }

    private BufferedImage readImage(File file, int width, int height) throws IOException {
        BufferedImage img = ImageIO.read(file);
        BufferedImage imgScale = scale(img, width, height);

        String path = "C:\\Users\\Jackie\\Downloads\\dd\\out\\cov";
        ImageIO.write(imgScale, "png", new File(path + File.separator + "960.png"));

        int w = imgScale.getWidth();
        int h = imgScale.getHeight();
        int x = width > w ? 0 : (w - width) / 2;
        int y = height > h ? 0 : (h - height) / 2;
        width = width > w ? w : width;
        height = height > h ? h : height;

        BufferedImage imgBuffer = cut(imgScale, x, y, width, height);
        Graphics2D g = imgBuffer.createGraphics();
        g.drawImage(imgScale, 0, 0, null);
        g.dispose();
        File f = new File(path);
        if (!f.exists()) {
            f.mkdir();
        }
        ImageIO.write(imgBuffer, "png", new File(path + File.separator + FileUtils.getFileName(file) + "-ex.png"));
        return imgBuffer;
    }

    private BufferedImage cut(BufferedImage img, int x, int y, int width, int height) {
        //调用裁剪方法
        BufferedImage image = img.getSubimage(x, y, width, height);
        return image;
    }

    private BufferedImage scale(BufferedImage img, int width, int height) throws IOException {
        int orgWidth = img.getWidth();
        int orgHeight = img.getHeight();
        double ratioX = (double) width / orgWidth;
        double ratioY = (double) height / orgHeight;
        double ratio = Math.max(ratioX, ratioY);
        ratio = ratio == 1 ? Math.min(ratioX, ratioY) : ratio;

        int w = (int) (orgWidth * ratio);
        int h = (int) (orgHeight * ratio);
        Image imgScale = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
        BufferedImage imgBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = imgBuffer.createGraphics();
        g.drawImage(imgScale, 0, 0, null);
        g.dispose();
        return imgBuffer;
    }

    void thumbnail(File rawImage, int pixel, File saltImage) throws IOException {
        BufferedImage source = ImageIO.read(rawImage);
        int width = source.getWidth();
        int height = source.getHeight();

        int l = width > height ? width : height;

        double ratio = (pixel * 1.0) / l;

        int w = (int) (width * ratio);
        int h = (int) (height * ratio);

        BufferedImage bi = getCompatibleImage(w, h);
        Graphics2D g2d = bi.createGraphics();
        double xScale = (double) w / width;
        double yScale = (double) h / height;
        AffineTransform at = AffineTransform.getScaleInstance(xScale, yScale);
        g2d.drawRenderedImage(source, at);
        g2d.dispose();
        ImageIO.write(bi, "jpg", saltImage);
    }

    private BufferedImage getCompatibleImage(int width, int height) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gd.getDefaultConfiguration();
        BufferedImage image = gc.createCompatibleImage(width, height);
        return image;
    }

}
